﻿// remove for WPF
#define Silverlight

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace Crossfader
{
    public partial class MediaElement : UserControl
    {
        private ObservableCollection<bool> IsChannelBusy = new ObservableCollection<bool>(); 
        private ObservableCollection<System.Windows.Controls.MediaElement> ChannelCollection = new ObservableCollection<System.Windows.Controls.MediaElement>();
        private string LastUri = string.Empty;
        private bool TemplateApplied = false;

        #if !Silverlight  
            private ObservableCollection<MediaPlayer> ChannelCollection2 = new ObservableCollection<MediaPlayer>();
        #endif 

        public int CurrentChannel = 0; 

        public MediaElement()
        {
            InitializeComponent();

            if (ChannelCount < 1)
            {
                ChannelCount = 5;
            }
 
            this.Loaded += new RoutedEventHandler(MediaElement_Loaded);
        }

        void MediaElement_Loaded(object sender, RoutedEventArgs e)
        {

            OnApplyTemplate();
        }

        public override void OnApplyTemplate()
        { 
            for (int x = 0; x < ChannelCount; x++)
            {
                System.Windows.Controls.MediaElement ChannelBase = new System.Windows.Controls.MediaElement();
                ChannelBase.Tag = x.ToString();
                ChannelBase.MediaFailed += new EventHandler<ExceptionRoutedEventArgs>(ClannelBase_MediaFailed);
                ChannelBase.MediaEnded += new RoutedEventHandler(ClannelBase_MediaEnded);

                #if !Silverlight  
                    MediaPlayer ChannelBase2 = new MediaPlayer();
                    ChannelBase2.Tag = x.ToString();
                    ChannelCollection2.Add(ChannelBase2);
                    ChannelCollection[x].MediaEnded += new EventHandler(MediaElement_MediaEnded); 
                #endif

                ChannelCollection.Add(ChannelBase);
                LayoutRoot.Children.Add(ChannelCollection[x]);

                IsChannelBusy.Add(false); 
            }
            TemplateApplied = true;
            if (!(string.IsNullOrEmpty(LastUri)))
            {
                SetSource(LastUri);
            }
        }

        #region dependency properties

        public static readonly DependencyProperty ChannelCountProperty = DependencyProperty.Register("ChannelCount", typeof(int), typeof(MediaElement), new PropertyMetadata(new PropertyChangedCallback(OnChannelCountChanged)));

        public int ChannelCount
        {
            get { return (int)GetValue(ChannelCountProperty); }
            set { SetValue(ChannelCountProperty, value); }
        }

        private static void OnChannelCountChanged(DependencyObject DpObj, DependencyPropertyChangedEventArgs e)
        { }

        public static readonly DependencyProperty AutoPlayProperty = DependencyProperty.Register("AutoPlay", typeof(bool), typeof(MediaElement), new PropertyMetadata(new PropertyChangedCallback(OnAutoPlayChanged)));

        public bool AutoPlay
        {
            get { return (bool)GetValue(AutoPlayProperty); }
            set { SetValue(AutoPlayProperty, value); }
        }

        private static void OnAutoPlayChanged(DependencyObject DpObj, DependencyPropertyChangedEventArgs e)
        { 
        }

        public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(string), typeof(MediaElement), new PropertyMetadata(new PropertyChangedCallback(OnSourceChanged)));

        public string Source
        {
            get { return (string)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        private static void OnSourceChanged(DependencyObject DpObj, DependencyPropertyChangedEventArgs e)
        {
            MediaElement ThisElement = DpObj as MediaElement;

            if (ThisElement != null)
            {
                ThisElement.SetSource(ThisElement.Source);
            }
        }

        #endregion

        public void SetSource(string NewUri)
        {
            LastUri = NewUri;
            if (TemplateApplied)
            {
                int x = 0;

                while (x > -1)
                {
                    if (x > (ChannelCount - 1))
                    {
                        x = 0;
                    }
                    if (!IsChannelBusy[x])
                    {
                        IsChannelBusy[x] = true;
                        SetSource(NewUri, x);
                        x = -1;
                        break;
                    }
                    x++;
                }
            }
        }

        private void SetSource(string NewUri, int indexer)
        { 
            Uri MediaItem = new Uri(NewUri, UriKind.RelativeOrAbsolute);

            #if !Silverlight 
                MediaPlayer ClannelBase =  ChannelCollection2[indexer];  
                ClannelBase.Open(MediaItem);  
            #else 
                System.Windows.Controls.MediaElement ClannelBase =  ChannelCollection[indexer];
                ClannelBase.Source = MediaItem;
                ClannelBase.AutoPlay = true;
            #endif

            CurrentChannel = indexer;

            ClannelBase.Play();
        }

        public void Play()
        {
            ChannelCollection[CurrentChannel].Play();
        }

        public void Stop()
        {
            ChannelCollection[CurrentChannel].Stop();
        }

        public void Pause()
        { 
            ChannelCollection[CurrentChannel].Pause();
        }

        #region event handlers

        private void ClannelBase_MediaFailed(object sender, ExceptionRoutedEventArgs e)
        {
            SetChannelBusyFromMediaElement((System.Windows.Controls.MediaElement)(sender)); 
        }
 
        private void ClannelBase_MediaEnded(object sender, RoutedEventArgs e)
        {
            SetChannelBusyFromMediaElement((System.Windows.Controls.MediaElement)(sender)); 
        }

        void MediaElement_MediaEnded(object sender, EventArgs e)
        { 
            #if !Silverlight 
                MediaPlayer MyPointer = ((MediaPlayer)(sender));
                string MyIndexer = ((string)(MyPointer.Tag));
                SetIsChannelBusy(MyIndexer);  
            #endif
        }

        #endregion

        #region tools and utilities

        private void SetChannelBusyFromMediaElement(System.Windows.Controls.MediaElement MyPointer)
        {
            string MyIndexer = ((string)(MyPointer.Tag));
            SetIsChannelBusy(MyIndexer);  
        }

        private void SetIsChannelBusy(string MyIndexer)
        {
                int TheFrakingRealIntThatCanNotBeFrakingUnboxed = int.Parse(MyIndexer); 
                IsChannelBusy[TheFrakingRealIntThatCanNotBeFrakingUnboxed] = false;
        }

        #endregion

    }
}
